package com.xtq.aop.proxy;

import com.xtq.annotations.After;
import com.xtq.annotations.Before;
import com.xtq.annotations.Pointcut;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AOPInvocationHandler implements InvocationHandler {
    private final Object target;
    private final List<Object> aspects;

    public AOPInvocationHandler(Object targetClassInstance, List<Object> aspects) {
        this.target = targetClassInstance;
        this.aspects = aspects;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 1. 执行 @Before 注解的切面方法
        invokeBefore(method);

        // 2. 执行目标方法
        Object result = method.invoke(target, args);

        // 3. 执行 @After 注解的切面方法
        invokeAfter(method);

        return result;
    }

  
    private void invokeBefore(Method method) throws InvocationTargetException, IllegalAccessException {
        for (Object aspect : aspects) {
            // 遍历切面类的方法
            for (Method aspectMethod : aspect.getClass().getDeclaredMethods()) {
                // 判断是否存在 @Pointcut 注解
                if (aspectMethod.isAnnotationPresent(Pointcut.class)) {
                    String pointcutExpression = aspectMethod.getAnnotation(Pointcut.class).value();
                    
                    // 如果切入点表达式与当前方法匹配，则执行 @Before 增强方法
                    if (matchesPointcut(pointcutExpression, method)) {
                        for (Method beforeMethod : aspect.getClass().getDeclaredMethods()) {
                            if (beforeMethod.isAnnotationPresent(Before.class)) {
                                System.out.println("代理执行的 Aspect Before: " + beforeMethod.getName());
                                beforeMethod.invoke(aspect);  // 执行 @Before 增强方法
                            }
                        }
                    }
                }
            }
        }
    }
    private void invokeAfter(Method method) throws InvocationTargetException, IllegalAccessException {
        for (Object aspect : aspects) {
            // 遍历切面类的方法
            for (Method aspectMethod : aspect.getClass().getDeclaredMethods()) {
                // 判断是否存在 @Pointcut 注解
                if (aspectMethod.isAnnotationPresent(Pointcut.class)) {
                    String pointcutExpression = aspectMethod.getAnnotation(Pointcut.class).value();
                    
                    // 如果切入点表达式与当前方法匹配，则执行 @After 增强方法
                    if (matchesPointcut(pointcutExpression, method)) {
                        for (Method afterMethod : aspect.getClass().getDeclaredMethods()) {
                            if (afterMethod.isAnnotationPresent(After.class)) {
                                System.out.println("代理执行的 Aspect After: " + afterMethod.getName());
                                afterMethod.invoke(aspect);  // 执行 @After 增强方法
                            }
                        }
                    }
                }
            }
        }
    }
    
    private boolean matchesPointcut(String pointcutExpression, Method method) {
        // 简单解析 execution(* UserService.addUser(..)) 格式的表达式
        Pattern pattern = Pattern.compile("execution\\(\\*\\s*(\\S+)\\.(\\S+)\\(.*\\)\\)");
        Matcher matcher = pattern.matcher(pointcutExpression);
        
        if (matcher.matches()) {
            String className = matcher.group(1);  // 类名
            String methodName = matcher.group(2);  // 方法名
            
            // 获取当前方法的类名和方法名
            String targetClassName = method.getDeclaringClass().getSimpleName();
            String targetMethodName = method.getName();
            
            // 判断是否匹配
            return targetMethodName.equals(methodName) && targetClassName.equals(className);
        }
        return false;
    }
    
}
